package cn.tqfeiyang.smartadmin.system.service;

import cn.tqfeiyang.smartadmin.commons.pagination.QueryParams;
import cn.tqfeiyang.smartadmin.commons.toolbox.CollectionUtils;
import cn.tqfeiyang.smartadmin.system.entity.MenuEntity;
import cn.tqfeiyang.smartadmin.system.entity.RoleEntity;
import cn.tqfeiyang.smartadmin.system.mapper.MenuMapper;
import cn.tqfeiyang.smartadmin.system.mapper.RoleMenuMapper;
import cn.tqfeiyang.smartadmin.system.request.MenuCreateDTO;
import cn.tqfeiyang.smartadmin.system.request.MenuUpdateDTO;
import cn.tqfeiyang.smartadmin.system.request.MenuQueryDTO;
import cn.tqfeiyang.smartadmin.system.response.MenuQueryVO;
import cn.tqfeiyang.smartadmin.system.response.MenuDetailVO;

import cn.tqfeiyang.smartadmin.system.response.RoleQueryVO;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.github.pagehelper.PageHelper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import cn.tqfeiyang.smartadmin.commons.exception.BusinessException;
import cn.tqfeiyang.smartadmin.commons.pagination.PageData;
import cn.tqfeiyang.smartadmin.commons.toolbox.BeanUtils;
import cn.tqfeiyang.smartadmin.commons.toolbox.ValidationUtils;

import java.util.List;
import java.util.Set;

/**
 * 菜单服务
 *
 * @author tqfeiyang
 * @since 2024-08-23
 */
@Service
public class MenuService {

    /**
     * 菜单映射接口
     */
    @Resource
    private MenuMapper menuMapper;

    /**
     * 角色-菜单映射接口
     */
    @Resource
    private RoleMenuMapper roleMenuMapper;

    /**
     * 查询菜单
     *
     * @param dto 请求数据
     * @return 菜单列表
     */
    public PageData<MenuQueryVO> queryMenus(MenuQueryDTO dto) {
        ValidationUtils.validateProperties(dto);
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        List<MenuEntity> list = menuMapper.selectList(dto.getWrapper());
        return PageData.create(list, MenuQueryVO.class);
    }

    /**
     * 获取菜单
     *
     * @param menuId 菜单id
     * @return 菜单信息
     */
    public MenuDetailVO readMenu(Long menuId) {
        MenuEntity menuEntity = checkMenuExists(menuId);
        return BeanUtils.map(menuEntity, MenuDetailVO.class);
    }

    /**
     * 添加菜单
     *
     * @param dto 请求数据
     * @return 菜单id
     */
    @Transactional(rollbackFor = Exception.class)
    public Long createMenu(MenuCreateDTO dto) {
        ValidationUtils.validateProperties(dto);
        MenuEntity menuEntity = BeanUtils.copy(dto, MenuEntity.class);
        menuMapper.insert(menuEntity);
        return menuEntity.getMenuId();
    }

    /**
     * 修改菜单
     *
     * @param menuId 菜单id
     * @param dto 请求数据
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateMenu(Long menuId, MenuUpdateDTO dto) {
        checkMenuExists(menuId);
        ValidationUtils.validateProperties(dto);
        MenuEntity menuEntity = BeanUtils.copy(dto, MenuEntity.class);
        menuEntity.setMenuId(menuId);
        menuMapper.updateById(menuEntity);
    }

    /**
     * 删除菜单
     *
     * @param menuId 菜单id
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteMenu(Long menuId) {
        checkMenuExists(menuId);
        menuMapper.deleteById(menuId);
        roleMenuMapper.deleteRoleIdsByMenuId(menuId);
    }

    /**
     * 检查菜单实体是否存在
     *
     * @param menuId 菜单id
     * @return 菜单实体
     */
    protected MenuEntity checkMenuExists(Long menuId) {
        Assert.notNull(menuId, "menuId不能为空");
        MenuEntity menuEntity = menuMapper.selectById(menuId);
        if (ObjectUtils.isEmpty(menuEntity)) {
            throw new BusinessException("菜单不存在");
        }
        return menuEntity;
    }

    /**
     * 查询角色
     *
     * @param menuId 菜单id
     * @param dto 请求数据
     * @return 角色列表
     */
    public PageData<RoleQueryVO> queryRoles(Long menuId, QueryParams dto) {
        checkMenuExists(menuId);
        ValidationUtils.validateProperties(dto);
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        List<RoleEntity> list = roleMenuMapper.selectRoleListByMenuId(menuId);
        return PageData.create(list, RoleQueryVO.class);
    }

    /**
     * 更新角色
     *
     * @param menuId 菜单id
     * @param roleIds 角色id集合
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateRoles(Long menuId, Set<Long> roleIds) {
        checkMenuExists(menuId);
        roleMenuMapper.deleteRoleIdsByMenuId(menuId);
        if (CollectionUtils.isNotEmpty(roleIds)) {
            roleMenuMapper.insertRoleIdsByMenuId(menuId, roleIds);
        }
    }

}
